home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / parsepattern.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  6KB  |  207 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: parsepattern.c,v 1.1 1996/09/11 12:54:46 digulla Exp $
  4.     $Log: parsepattern.c,v $
  5.     Revision 1.1  1996/09/11 12:54:46  digulla
  6.     A couple of new DOS functions from M. Fleischer
  7.  
  8.     Desc:
  9.     Lang: english
  10. */
  11. #include <clib/exec_protos.h>
  12. #include <dos/dos.h>
  13. #include <dos/dosasl.h>
  14. #include "dos_intern.h"
  15.  
  16. /*****************************************************************************
  17.  
  18.     NAME */
  19.     #include <clib/dos_protos.h>
  20.  
  21.     __AROS_LH3(LONG, ParsePattern,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LHA(STRPTR, Source,      D1),
  25.     __AROS_LHA(STRPTR, Dest,        D2),
  26.     __AROS_LHA(LONG,   DestLength,  D3),
  27.  
  28. /*  LOCATION */
  29.     struct DosLibrary *, DOSBase, 140, Dos)
  30.  
  31. /*  FUNCTION
  32.     Takes a pattern containing wildcards and transforms it into some
  33.     intermediate representation for use with the MathPattern() function.
  34.     The intermediate representation is longer but generally a buffer
  35.     size of 2*(strlen(Source)+1) is enough. Nevertheless you should check
  36.     the returncode to be sure that everything went fine.
  37.  
  38.     INPUTS
  39.     Source     - Pattern describing the kind of strings that match.
  40.              Possible tokens are:
  41.              #x     - The following character or item is repeaded 0 or
  42.                       more times.
  43.              ?      - Item matching a single non-NUL character.
  44.              a|b|c  - Matches one of multiple strings.
  45.              ~x     - This item matches if the item x doesn't match.
  46.              (a)    - Parens
  47.              [a-z]  - Matches a single character out of the set.
  48.              [~a-z] - Matches a single non-NUL character not in the set.
  49.              'c     - Escapes the following character.
  50.              *      - Same as #?, but optional.
  51.     Dest       - Buffer for the destination.
  52.     DestLength - Size of the buffer.
  53.  
  54.     RESULT
  55.      1 - There are wildcards in the pattern (it might match more than
  56.          one string).
  57.      0 - No wildcards in it, all went fine.
  58.     -1 - An error happened. IoErr() gives additional information in
  59.          that case.
  60.  
  61.     NOTES
  62.  
  63.     EXAMPLE
  64.  
  65.     BUGS
  66.  
  67.     SEE ALSO
  68.  
  69.     INTERNALS
  70.  
  71.     HISTORY
  72.     29-10-95    digulla automatically created from
  73.                 dos_lib.fd and clib/dos_protos.h
  74.  
  75. *****************************************************************************/
  76. {
  77.     __AROS_FUNC_INIT
  78.     __AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
  79.     STRPTR stack, end;
  80.     UBYTE a, b, t;
  81.     LONG iswild=0;
  82.  
  83.     LONG *result=&((struct Process *)FindTask(NULL))->pr_Result2;
  84. #define ERROR(a) { *result=a; return -1; }
  85.     stack=end=Dest+DestLength;
  86. #define PUT(a) { if(Dest>=stack) ERROR(ERROR_BUFFER_OVERFLOW); *Dest++=(a); }
  87.     
  88.     if(!*Source)
  89.     {
  90.         PUT(0);
  91.         return 0;
  92.     }else
  93.         PUT(MP_OR);
  94.  
  95.     while(*Source)
  96.     {
  97.         switch(*Source++)
  98.         {
  99.             case '#':
  100.                 iswild=1;
  101.                 if(*Source=='?')
  102.                 {
  103.                     Source++;
  104.                     PUT(MP_ALL);
  105.                 }else
  106.                 {
  107.                     PUT(MP_MULT);
  108.                     *--stack=MP_MULT_END;
  109.                     continue;
  110.                 }
  111.                 break;
  112.             case '~':
  113.                 iswild=1;
  114.                 PUT(MP_NOT);
  115.                 *--stack=MP_NOT_END;
  116.                 continue;
  117.             case '?':
  118.                 iswild=1;
  119.                 PUT(MP_SINGLE);
  120.                 break;
  121.             case '(':
  122.                 PUT(MP_OR);
  123.                 *--stack=MP_OR_END;
  124.                 continue;
  125.             case '|':
  126.                 iswild=1;
  127.                 if(stack!=end&&*stack!=MP_OR_END)
  128.                     ERROR(ERROR_BAD_TEMPLATE);
  129.                 PUT(MP_OR_NEXT);
  130.                 break;
  131.             case ')':
  132.                 if(stack==end||*stack!=MP_OR_END)
  133.                     ERROR(ERROR_BAD_TEMPLATE);
  134.                 PUT(*stack++);
  135.                 break;
  136.             case '[':
  137.                 if(*Source=='~')
  138.                 {
  139.                     Source++;
  140.                     PUT(MP_NOT_SET);
  141.                 }else
  142.                     PUT(MP_SET);
  143.                 a=*Source++;
  144.                 if(!a)
  145.                     ERROR(ERROR_BAD_TEMPLATE);
  146.                 do
  147.                 {
  148.                     if(Source[0]=='-'&&Source[1]!=']')
  149.                     {
  150.                         Source++;
  151.                         b=*Source++;
  152.                         if(!b)
  153.                             ERROR(ERROR_BAD_TEMPLATE);
  154.                         if(b>a)
  155.                             t=a, a=b, b=t;
  156.                         PUT(MP_DASH);
  157.                         if(b>=0x81&&b<=0x8e)
  158.                         {
  159.                             PUT(MP_ESCAPE);
  160.                             b-=0x80;
  161.                         }
  162.                         PUT(b);
  163.                     }
  164.                     if(a>=0x81&&a<=0x8e)
  165.                     {
  166.                         PUT(MP_ESCAPE);
  167.                         a-=0x80;
  168.                     }
  169.                     PUT(a);
  170.                     a=*Source++;
  171.                     if(!a)
  172.                         ERROR(ERROR_BAD_TEMPLATE);
  173.                 }while(a!=']');
  174.                 PUT(MP_SET_END);
  175.                 break;
  176.             case '*':
  177.                 if(DOSBase->dl_Flags&RNF_WILDSTAR)
  178.                 {
  179.                     PUT(MP_ALL);
  180.                 }else
  181.                     PUT('*');
  182.                 break;
  183.             case '\'':
  184.                 if(!*Source++)
  185.                     ERROR(ERROR_BAD_TEMPLATE);
  186.                 /* Fall through */
  187.             default:
  188.                 a=Source[-1];
  189.                 if(a>=0x81&&a<=0x8e)
  190.                 {
  191.                     PUT(MP_ESCAPE);
  192.                     a-=0x80;
  193.                 }
  194.                 PUT(a);
  195.                 break;
  196.         }
  197.         while(stack!=end&&*stack!=MP_OR_END)
  198.             PUT(*stack++);
  199.     }
  200.     if(stack!=end)
  201.         ERROR(ERROR_BAD_TEMPLATE);
  202.     PUT(MP_OR_END);
  203.     PUT(0);
  204.     return iswild;
  205.     __AROS_FUNC_EXIT
  206. } /* ParsePattern */
  207.